package com.zengdada.authority.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zengdada.authority.config.security.intercept.AuthorityUtil;
import com.zengdada.authority.exception.RoutineException;
import com.zengdada.authority.mapper.*;
import com.zengdada.authority.model.*;
import com.zengdada.authority.service.DynamicPageAuthorityService;
import com.zengdada.authority.service.DynamicTableAuthorityService;
import com.zengdada.authority.service.DynamicTableToolbarService;
import com.zengdada.authority.service.EnhanceBaseService;
import com.zengdada.authority.utils.CommonUtils;
import com.zengdada.authority.utils.where.Where;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.weekend.Fn;
import tk.mybatis.mapper.weekend.WeekendSqls;
import tk.mybatis.mapper.weekend.reflection.Reflections;

import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.zengdada.authority.utils.where.Where.Formula.AND;

/**
 * @Auther: 12614
 * @Contact: 1261438511@qq.com
 * @Date: 2019/3/7 11:03
 * @Description:
 */
@Service
public class DynamicPageAuthorityServiceImpl extends EnhanceBaseService<DynamicPage> implements DynamicPageAuthorityService {

    @Autowired
    DynamicPageTableRelMapper dynamicPageTableRelMapper;
    @Autowired
    @Qualifier("dynamicTableAuthorityServiceImpl")
    DynamicTableAuthorityService dynamicTableAuthorityService;
    @Autowired
    DynamicTableColumnMapper dynamicTableColumnMapper;
    @Autowired
    DynamicTableColumnSearchMapper dynamicTableColumnSearchMapper;
    @Autowired
    DynamicTableSearchMapper dynamicTableSearchMapper;
    @Autowired
    DmlColumnMapper dmlColumnMapper;
    @Autowired
    PublicSqlMapper publicSqlMapper;
    @Autowired
    @Qualifier("dynamicTableToolbarServiceImpl")
    DynamicTableToolbarService dynamicTableToolbarService;

    @Value("${server.servlet.context-path}")
    private String CONTEXT_PATH;

    private static Pattern NUMBER_PATTERN = Pattern.compile("^[-\\+]?[\\d]*$");


    @Override
    public int save(DynamicPage dynamicPage) {
        dynamicPage.setModifyUser(AuthorityUtil.getLoginUser1(false).getId());
        if (StringUtils.isBlank(dynamicPage.getId())) {
            try {
                CommonUtils.reflectObjectTransString(dynamicPage, false);
            } catch (Exception e) {
                throw new RoutineException(e.getMessage());
            }
            return this.add(dynamicPage);
        } else {
            dynamicPage.setModifyTime(new Date());
            return this.updateById(dynamicPage);
        }
    }

    @Override
    public Map<String, Object> createPageData(String pageId) {
        Map<String, Object> result = new HashMap<>();
        DynamicPage dynamicPage = this.selectById(pageId);
        if (dynamicPage == null || dynamicPage.getState() != 1)
            throw new RuntimeException(String.format("没有找到 pageId 为 %s 的数据", pageId));
        List<String> tableIds = dynamicPageTableRelMapper.selectByExample(new Example.Builder(DynamicPageTableRel.class)
                .orderByAsc(Reflections.fnToFieldName((Fn<DynamicPageTableRel, Object>) DynamicPageTableRel::getSort))
                .where(WeekendSqls.<DynamicPageTableRel>custom().andEqualTo(DynamicPageTableRel::getPageId, pageId)).build()).stream().map(i -> i.getTableId()).collect(Collectors.toList());
        if (tableIds.size() == 0) throw new RoutineException("请配置表格！！");
        List<Map<String, Object>> tables = dynamicTableAuthorityService.selectDetailedPageInfoByParam(
                new Where(AND,
                        Arrays.asList(
                                new Where(Reflections.fnToFieldName((Fn<DynamicTable, Object>) DynamicTable::getState), "1", Where.FieldType.NUMBER),
                                new Where(Reflections.fnToFieldName((Fn<DynamicTable, Object>) DynamicTable::getId), Where.Formula.IN, StringUtils.join(tableIds, ','))
                        )
                ), null, null).getList();
        List<Map<String, Object>> configs = new ArrayList<>();
        for (Map<String, Object> table : tables) {
            configs.add(analysisTableConfig(table));
        }

        result.put("page", dynamicPage);
        result.put("config", configs);
        return result;
    }


    @Override
    public List<Map<String, Object>> createPageDataByTableId(String tableId) {
        Map<String, Object> table = CommonUtils.batchOrSingleBeanToMap(dynamicTableAuthorityService.selectById(tableId), DynamicTable.class.getPackage().getName());
        if (table == null) throw new RoutineException("没有找到相关配置信息！！");
        return new ArrayList<Map<String, Object>>() {{
            add(analysisTableConfig(table));
        }};
    }


    private Map<String, Object> analysisTableConfig(Map<String, Object> table) {
        dataFormat(table); // 转换数据 排空 替换通配符
        // 查询当前表格字段
        List<Map<String, Object>> tableColumns = CommonUtils.batchOrSingleBeanToMap(dynamicTableColumnMapper.selectByExample(new Example.Builder(DynamicTableColumn.class)
                .where(WeekendSqls.<DynamicTableColumn>custom()
                        .andEqualTo(DynamicTableColumn::getDynamicTableId, table.get("id"))
                        .andEqualTo(DynamicTableColumn::getState, 1))
                .orderByAsc(Reflections.fnToFieldName((Fn<DynamicTableColumn, Object>) DynamicTableColumn::getSort)).build()), DynamicTableColumn.class.getPackage().getName());
        if (tableColumns.size() == 0) throw new RoutineException(String.format("请配置表格（%s）表头信息", table.get("title")));
        // 查询当前表格DML的字段信息
        List<DmlColumn> columns = dmlColumnMapper.selectByExample(new Example.Builder(DmlColumn.class).where(WeekendSqls.<DmlColumn>custom()
                .andEqualTo(DmlColumn::getDmlId, table.get("dmlId")).andEqualTo(DmlColumn::getIsValid, 1)).build());
        // 查询当前表字段搜索配置
        List<DynamicTableColumnSearch> searchs = dynamicTableColumnSearchMapper.selectByExample(new Example.Builder(DynamicTableColumnSearch.class)
                .where(WeekendSqls.<DynamicTableColumnSearch>custom().andIn(DynamicTableColumnSearch::getId, tableColumns.stream().map(e -> e.get("id")).collect(Collectors.toList()))).build());
        List<Map<String, Object>> search_config_datas = new ArrayList<>();
        // 查询当前表搜索配置
        DynamicTableSearch dynamicTableSearch = dynamicTableSearchMapper.selectByPrimaryKey(table.get("id"));
        Map<String, Object> tableSearch = CommonUtils.batchOrSingleBeanToMap(dynamicTableSearch == null ? new HashMap<>() : dynamicTableSearch, DynamicTableSearch.class.getPackage().getName());
        tableSearch.put("data", search_config_datas);
        //查询toolbar配置
        List<DynamicTableToolbar> toolbars = dynamicTableToolbarService.selectByTableId(String.valueOf(table.get("id")));
        // 解析表格字段
        Iterator<Map<String, Object>> iterator = tableColumns.iterator();
        while (iterator.hasNext()) {
            Map<String, Object> tableColumn = iterator.next();
//        tableColumns.forEach(tableColumn -> {
            dataFormat(tableColumn); // 转换数据 排空 替换通配符
            try {
                if (tableColumn.get("dmlColumnId") != null) {
                    DmlColumn column = columns.stream().filter(i -> tableColumn.get("dmlColumnId").equals(i.getId())).collect(Collectors.toList()).get(0);
                    tableColumn.put("field", column.getLabel());
                    tableColumn.put("attrs", column.getAttrs());
                    tableColumn.put("sort", (column.getAttrs() & 64) == 64);
                    tableColumn.put("search", (column.getAttrs() & 256) == 256);
                }
            } catch (Exception e) {
                tableColumn.remove("field");
                tableColumn.remove("sort");
            }
            tableColumn.remove("dmlColumnId");
            tableColumn.remove("state");
            tableColumn.remove("dynamicTableId");
            if (tableColumn.get("toolbar") != null) {
                tableColumn.put("toolbar", "#" + tableColumn.get("toolbar"));
            }
            Iterator<DynamicTableColumnSearch> it = searchs.iterator();
            // 解析查询字段
            while (it.hasNext()) {
                Map<String, Object> search_config = CommonUtils.batchOrSingleBeanToMap(it.next(), DynamicTableColumnSearch.class.getPackage().getName());
                if (tableColumn.get("id").equals(search_config.get("id"))) {
                    if (!"true".equals(String.valueOf(tableColumn.get("search")))) {
                        it.remove();
                        break;
                    }
                    try {
                        search_config.put("field", tableColumn.get("field"));
                        search_config.put("title", tableColumn.get("title"));
                        String dataSource = String.valueOf(search_config.get("dataSource"));
                        try {
                            search_config.put("options", JSONArray.parseArray(dataSource, Map.class));
                        } catch (Exception e) {
                            try {
                                search_config.put("options", publicSqlMapper.selectDataSimple(dataSource));
                            } catch (Exception e1) {
                                search_config.put("editType", "text");
                            }
                        }
                        search_config.remove("id");
                        search_config.remove("dataSource");
                        dataFormat(search_config);
                        search_config_datas.add(search_config);
                    } catch (Exception e) { // 解析异常就移除
                        it.remove();
                    }
                    break;
                }
            }
            Object attrs = tableColumn.get("attrs");
            if (attrs != null && (Integer.valueOf(attrs.toString()) & 512) != 512)
                iterator.remove();
            else {
                tableColumn.remove("attrs");
                tableColumn.remove("search");
            }
        }
//        });

        table.put("url", String.format("%sauthority/plat/dml/paging_query.do", CONTEXT_PATH));
        table.put("elem", String.format("#%s-table", table.get("id")));
        table.put("where", JSONObject.parse("{\"dmlId\":\"" + table.get("dmlId") + "\",\"selectType\":2}"));
        table.put("cols", new ArrayList<Object>() {{
            add(tableColumns);
        }});
        table.remove("state");
        table.remove("modifyUser");
        table.remove("modifyUserName");
        table.remove("modifyTime");
        table.remove("dmlId");
        table.remove("dmlName");

        return new HashMap<String, Object>() {{
            put("table_config", table);
            put("toolbar_config", toolbars);
            put("search_config", new HashMap<String, Object>() {{
                put("config", tableSearch);
            }});
        }};
    }

    private void dataFormat(Map<String, Object> map) {
        Map<String, Object> tempMap = new HashMap<>();
        for (Iterator<Map.Entry<String, Object>> it = map.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry<String, Object> entry = it.next();
            if (entry.getValue() == null || entry.getValue().equals("null")) {
                it.remove();
                continue;
            }
            if (entry.getKey().indexOf("dis") == 0) { //替换通用符号 dis
                tempMap.put((new StringBuilder()).append(Character.toLowerCase(entry.getKey().charAt(3))).append(entry.getKey().substring(4)).toString(), entry.getValue());
                it.remove();
                continue;
            }
        }
        map.putAll(tempMap);
        tempMap.clear();
        map.forEach((k, v) -> {
            // 转换 boolean 值
            if ("true".equals(String.valueOf(v).toLowerCase()) || "false".equals(String.valueOf(v).toLowerCase()))
                map.put(k, Boolean.valueOf(String.valueOf(v)));
            // 转换 数 值
            if (v instanceof String && NUMBER_PATTERN.matcher(String.valueOf(v)).matches())
                try {
                    map.put(k, Integer.valueOf(String.valueOf(v)));
                } catch (NumberFormatException e) {
                    // 什么都不做，理论上不会报错
                }
            // 转换字符串json数据和对象
            if (v instanceof String && v.toString().trim().startsWith("[") && v.toString().trim().endsWith("]"))
                map.put(k, JSONArray.parse(String.valueOf(v)));
            if (v instanceof String && v.toString().trim().startsWith("{") && v.toString().trim().endsWith("}"))
                map.put(k, JSONObject.parse(String.valueOf(v)));
            //提取js方法 加以标识 替换"号(使其直接可用)
//            if (v instanceof String && v.toString().contains("function(")) map.put(k, String.format("&n;%s&n;", v));
        });
    }
}
